#include "BufBlockMgr.h"
#include "MemPool.h"
#include "BufChunkMgr.h"

#define BLOCK_SIZE 2048

CBufBlockMgr::CBufBlockMgr(CBufChunkMgr *pChunks) : m_pChunks(pChunks)
{
}

CBufBlockMgr::~CBufBlockMgr()
{
    Destroy();
}

void *CBufBlockMgr::operator new(size_t sz)
{
    CMemPool *mp = CMemPool::GetInstance();

    if (nullptr == mp)
        return NULL;

    return mp->Alloc(sz);
}

void CBufBlockMgr::operator delete(void *ptr)
{
    CMemPool *mp = CMemPool::GetInstance();

    if (nullptr != mp)
        mp->Free(ptr);
}

// 不作任何操作，CBufChunks在释放内存时，会将所有内存释放
// 析构会调用到此，m_lstFree节点的内存不是它自身分配的，
// 析构节点会出错，故需在此删除节点
void CBufBlockMgr::Destroy()
{
    BufBlockNode *pHead = m_lstFree.GetHeader();

    while (nullptr != pHead)
    {
        m_lstFree.Remove(pHead);
        DeleteBlock(pHead);
        pHead = m_lstFree.GetHeader();
    }
}

BufBlockNode *CBufBlockMgr::GetBlock()
{
    BufBlockNode *pNode = nullptr;

    if (m_lstFree.IsEmpty())
        pNode = NewBlock();
    else
        pNode = m_lstFree.PopFront();

    if (nullptr != pNode)
    {
        pNode->pBuf = (uint8_t *)pNode + sizeof(BufBlockNode);
        pNode->nEnd = BLOCK_SIZE - sizeof(BufBlockNode);
        pNode->nRead = pNode->nWrite = 0;
    }

    return pNode;
}

bool CBufBlockMgr::FreeBlock(BufBlockNode *pNode)
{
    if (nullptr == pNode)
        return false;

    return m_lstFree.PushBack(pNode);
}

BufBlockNode *CBufBlockMgr::NewBlock()
{
    void *ptr = nullptr;
    BufBlockNode *pNode = nullptr;

    if (nullptr == m_pChunks)
        return nullptr;

    // BufBlockNode 没有使用MemPool中的内存
    // 需自己释放m_lstFree中节点的内存，避免出错
    ptr = m_pChunks->Alloc(BLOCK_SIZE);

    if (nullptr != ptr)
        pNode = m_lstFree.NewNode(ptr);

    return pNode;
}

void CBufBlockMgr::DeleteBlock(BufBlockNode *pNode)
{
    // 不做操作，程序结束时释放大块内存时，包含了本小快
}